package com.yq.ylmall.product.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yq.ylmall.constant.ProductConstant;
import com.yq.ylmall.exception.ServiceException;
import com.yq.ylmall.model.product.Region;
import com.yq.ylmall.product.mapper.RegionMapper;
import com.yq.ylmall.product.service.IRegionService;
import com.yq.ylmall.product.utils.ExcelHelper;
import com.yq.ylmall.product.utils.RegionExcelHelper;
import com.yq.ylmall.product.utils.RegionHelper;
import com.yq.ylmall.result.ResultCode;
import com.yq.ylmall.service.CacheService;
import com.yq.ylmall.vo.product.RegionExcelVo;
import com.yq.ylmall.vo.product.RegionVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 地区分类 服务实现类
 * </p>
 *
 * @author lsx
 * @since 2024-6-11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class IRegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements IRegionService {
    private final CacheService cacheService;

    // 添加缓存
    @Override
    public String findAll() {
        //查询缓存
        String cache = cacheService.get(ProductConstant.PRODUCT_REGION_CACHE);
        if (StrUtil.isNotBlank(cache)) return cache; //命中缓存，返回数据
        if (cache != null) return null;
        //未命中缓存，访问数据库
        List<Region> regions = baseMapper.selectList(Wrappers.<Region>lambdaQuery().orderByDesc(Region::getCode));

        //查询数据库，数据库为空，缓存空数据，并返回null
        if (regions.isEmpty()) {
            cacheService.setEx(ProductConstant.PRODUCT_REGION_CACHE, "", 3600, TimeUnit.SECONDS);
            return null;
        }
        //递归构建地区数据，缓存到Redis，并设置1天过期时间
        String result = JSON.toJSONString(RegionHelper.buildTree(regions));
        cacheService.setEx(ProductConstant.PRODUCT_REGION_CACHE, result, 3600, TimeUnit.SECONDS);
        return result;
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            //1.设置响应头信息和其他信息
            // 设置响应结果类型
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("地区数据", "UTF-8");
            //设置响应头信息
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
            //2.调用mapper方法查询所有分类，返回list集合
            List<Region> regionList = baseMapper.selectList(null);
            List<RegionExcelVo> regionExcelVoList = new ArrayList<>();
            //类型转换
            for (Region region : regionList) {
                RegionExcelVo regionExcelVo = new RegionExcelVo();
                BeanUtils.copyProperties(region,regionExcelVo);
                regionExcelVoList.add(regionExcelVo);
            }
            //3.调用easyexcel的write方法完成写操作
            EasyExcel.write(response.getOutputStream(),RegionExcelVo.class).sheet("地区数据").doWrite(regionExcelVoList);
        }catch (Exception e) {
            log.error("文件下载失败", e);
            throw new ServiceException(ResultCode.FILE_DOWNLOAD_FAIL);
        }
    }

    @Override
    public void importData(MultipartFile file) {
        try {
            //创建监听器对象，传递mapper对象
            RegionExcelHelper<RegionExcelVo> regionExcelHelper = new RegionExcelHelper<>(baseMapper);
            //调用read方法读取excel数据
            EasyExcel.read(file.getInputStream(),RegionExcelVo.class,regionExcelHelper).sheet().doRead();
            cacheService.delete(ProductConstant.PRODUCT_REGION_CACHE);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ServiceException(ResultCode.DATA_ERROR);
        }
    }
}
